package com.baofu.paycore.service;

import com.baofu.paycore.biz.model.BackPayBO;
import com.baofu.paycore.biz.paycore.handler.impl.CancelTransferHandler;
import com.baofu.paycore.biz.paycore.handler.impl.TransferHandler;
import com.baofu.paycore.biz.paycore.handler.impl.UnfreezeTransferHandler;
import com.baofu.paycore.common.enums.FlagEnum;
import com.baofu.paycore.common.utils.ExceptionUtil;
import com.baofu.paycore.manager.model.TransferBO;
import com.baofu.paycore.manager.storer.TransferOrderRepository;
import com.baofu.paycore.service.converter.BO2DTOConverter;
import com.baofu.paycore.service.facade.TransferServiceFacade;
import com.baofu.paycore.service.facade.enums.PayStatusEnums;
import com.baofu.paycore.service.facade.model.CancelResDTO;
import com.baofu.paycore.service.facade.model.transfer.*;
import com.baofu.paycore.service.factory.impl.CancelTransferFactoryImpl;
import com.baofu.paycore.service.factory.impl.TransferFactoryImpl;
import com.baofu.paycore.service.factory.impl.UnfreezeTransferFactoryImpl;
import com.baofu.paycore.service.validate.impl.transfer.CancelTransferValidate;
import com.baofu.paycore.service.validate.impl.transfer.TransferValidate;
import com.baofu.paycore.service.validate.impl.transfer.UnfreezeTransferValidate;
import com.system.commons.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.slf4j.helpers.SystemMarker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;

/**
 * 转账接口
 *
 * <p>
 *     1 转账接口
 *     2、转账撤销接口
 * </p>
 * User: LZQ Date: 2016/05/19  Version: 1.0
 */
@Slf4j
@Service
public class TransferService implements TransferServiceFacade {

    /**
     * 转账校验服务
     */
    @Autowired
    private TransferValidate transferValidate;

    /**
     * 支付模型服务
     */
    @Autowired
    private TransferFactoryImpl payBaseFactory;

    /**
     * 转账单存储
     */
    @Resource
    private TransferOrderRepository transferOrderRepository;

    /**
     * 转账业务处理
     */
    @Resource
    private TransferHandler transferHandler;

    /**
     * 转账撤销
     */
    @Autowired
    private CancelTransferValidate cancelTransferValidate;

    /**
     * 撤销转账模型组装
     */
    @Autowired
    private CancelTransferFactoryImpl cancelTransferFactory;

    /**
     * 转账撤销流程处理
     */
    @Autowired
    private CancelTransferHandler cancelTransferHandler;

    /**
     * 解冻转账校验
     */
    @Autowired
    private UnfreezeTransferValidate unfreezeTransferValidate;

    /**
     * 解冻转账工厂类
     */
    @Autowired
    private UnfreezeTransferFactoryImpl unfreezeTransferFactory;

    /**
     * 解冻转账流程处理
     */
    @Autowired
    private UnfreezeTransferHandler unfreezeTransferHandler;

    /**
     * 转账接口
     *
     * @param transferDTO 转账请求参数
     * @return 转账结果
     * response.isSuccess()标示方法的远程调用状态，方法实际执行结果从result 取值
     */
    @Override
    public Result<TransferResDTO> transfer(TransferDTO transferDTO,String tradeLogId) {
        long start = System.currentTimeMillis();
        boolean flag = false;
        Result<TransferResDTO> result = null;
        try {
            MDC.put(SystemMarker.TRACE_LOG_ID, tradeLogId);

            log.info("转账请求参数 :{}", transferDTO);
            flag = transferValidate.lock(transferDTO);

            //1、请求对象参数校验
            transferValidate.paramsValidate(transferDTO);
            if (StringUtils.isEmpty(transferDTO.getFeeFlag())) {
                transferDTO.setFeeFlag(FlagEnum.FALSE.getCode());
            }

            //2、冪等性校验
            result = transferValidate.validateUniqueOrder(transferDTO, transferOrderRepository, TransferResDTO.class) ;
            if (result != null) {
                TransferResDTO transferResDTO = result.getResult();
                transferResDTO.setRespDate(new Date());
                transferResDTO.setRealRtnFlag(payBaseFactory.getRealRtnFlag(transferResDTO.getStatus()));
                return result;
            }

            //3、请求对象转换
            TransferBO transferBO = payBaseFactory.build(transferDTO);
            transferBO.setTradeLogId(tradeLogId);

            //4、消费相关信息落地
            transferOrderRepository.addOrder(transferBO);

            //5、业务流程处理
            BackPayBO backPayBO = transferHandler.process(transferBO);
            //6、接口返回对象生成
            result = new Result<>(BO2DTOConverter.getTransferResDTO(backPayBO));

        } catch (Exception e) {

            log.error("转账异常 EXCEPTION:{}", e);
            result = ExceptionUtil.doExceptionService(e,TransferResDTO.class);
        } finally {
            log.info("transfer 耗时:{},转账处理结果:{}",System.currentTimeMillis() - start,result);
            transferValidate.release(transferDTO,flag);
            MDC.clear();
        }
        return result;
    }

    /**
     * 转账撤销接口
     *
     * @param cancelTransferDTO 转账撤销请求参数
     * @param tradeLogId        日志id
     * @return response.isSuccess()标示方法的远程调用状态，方法实际执行结果从result 取值
     */
    @Override
    public Result<CancelResDTO> cancelTransfer(CancelTransferDTO cancelTransferDTO, String tradeLogId) {
        long start = System.currentTimeMillis();
        boolean flag = false;
        Result<CancelResDTO> result = null;
        try {
            MDC.put(SystemMarker.TRACE_LOG_ID, tradeLogId);

            log.info("转账撤销请求参数 :{}", cancelTransferDTO);
            flag = cancelTransferValidate.lock(cancelTransferDTO);

            //1、冪等性校验
            result = cancelTransferValidate.validateUniqueOrder(cancelTransferDTO,transferOrderRepository,CancelResDTO.class) ;
            if (result != null) {
                CancelResDTO cacelResDTO = result.getResult();
                cacelResDTO.setRespDate(new Date());
                cacelResDTO.setRealRtnFlag(true);
                return result;
            }

            //2、请求对象参数校验
            TransferBO oldBo = cancelTransferValidate.validate(cancelTransferDTO);

            //3、请求对象转换
            TransferBO cancelTransferBO = cancelTransferFactory.build(cancelTransferDTO,oldBo);
            cancelTransferBO.setTradeLogId(tradeLogId);

            //4、消费相关信息落地
            transferOrderRepository.addOrder(cancelTransferBO);

            //5、业务流程处理
            BackPayBO backPayBO = cancelTransferHandler.process(cancelTransferBO);

            //6、接口返回对象生成
            result = new Result<>(BO2DTOConverter.getCancelTransferResDTO(backPayBO));
        } catch (Exception e) {

            log.error("转账撤销异常 EXCEPTION:{}", e);
            result = ExceptionUtil.doExceptionService(e,CancelResDTO.class);
        } finally {
            log.info("transfer撤销 耗时:{} 转账撤销处理结果:{}",System.currentTimeMillis() - start,result);
            cancelTransferValidate.release(cancelTransferDTO,flag);
            MDC.clear();
        }
        return result;
    }

    /**
     * 解冻转账接口
     * @param unfreezeTransferDTO       解冻转账参数
     * @param tradeLogId                日志ID
     * @return                          Result<UnfreezeTransferResDTO>
     */
    @Override
    public Result<UnfreezeTransferResDTO> unfreezeTransfer(UnfreezeTransferDTO unfreezeTransferDTO, String tradeLogId) {
        long start = System.currentTimeMillis();
        boolean flag = false;
        Result<UnfreezeTransferResDTO> result = null;
        try {
            MDC.put(SystemMarker.TRACE_LOG_ID, tradeLogId);

            log.info("解冻转账请求参数 :{}", unfreezeTransferDTO);
            flag = unfreezeTransferValidate.lock(unfreezeTransferDTO);

            //1、请求对象参数校验
            unfreezeTransferValidate.paramsValidate(unfreezeTransferDTO);

            //2.冪等性校验
            result = unfreezeTransferValidate.validateUniqueOrder(unfreezeTransferDTO, transferOrderRepository,
                    UnfreezeTransferResDTO.class);
            if (result != null) {
                UnfreezeTransferResDTO unfreezeTransferResDTO = result.getResult();
                unfreezeTransferResDTO.setRespDate(new Date());
                unfreezeTransferResDTO.setRealRtnFlag(true);
                return result;
            }

            //3、请求对象转换
            TransferBO transferBO = unfreezeTransferFactory.build(unfreezeTransferDTO);
            transferBO.setTradeLogId(tradeLogId);

            //4、消费相关信息落地
            transferOrderRepository.addOrder(transferBO);

            //5、业务流程处理
            BackPayBO backPayBO = unfreezeTransferHandler.process(transferBO);
            
            //6、接口返回对象生成
            result = new Result<>(BO2DTOConverter.getUnfreezeTransferResDTO(backPayBO));

        } catch (Exception e) {

            log.error("转账异常 EXCEPTION:{}", e);
            result = ExceptionUtil.doExceptionService(e, UnfreezeTransferResDTO.class);
        } finally {
            log.info("transfer 耗时:{},转账处理结果:{}", System.currentTimeMillis() - start, result);
            unfreezeTransferValidate.release(unfreezeTransferDTO, flag);
            MDC.clear();
        }
        return result;
    }

}
